package crawler;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.Status;

import java.io.*;
import java.util.Vector;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.nio.ByteBuffer;


import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;


public class TwitterCrawler {

	private Twitter twitter;
	public String favFile;
	public String tweetFile;
    private Database m_db;
    private Environment m_env;
   	
	public TwitterCrawler(String dirPath, String name) {
		
		twitter = new Twitter("favIndex", "danandjing");
		//twitter = new Twitter();
		try {
			// Open the environment. Create it if it does not already exist.
			EnvironmentConfig envConfig = new EnvironmentConfig();
			// envConfig.setCacheSize(56 * 1024 * 1024);
			envConfig.setAllowCreate(true);
			m_env = new Environment(new File(dirPath), envConfig);

			// Open the database. Create it if it does not already exist.
			DatabaseConfig dbConfig = new DatabaseConfig();
			dbConfig.setAllowCreate(true);
			m_db = m_env.openDatabase(null, name, dbConfig);
		} catch (DatabaseException dbe) {
			// Exception handling goes here
			dbe.printStackTrace();
		}

	}
	
    private DatabaseEntry getKeyEntry(long key) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(key);
        DatabaseEntry entry = new DatabaseEntry(buffer.array());
        return entry;
    }
    
    private DatabaseEntry getValueEntry() {
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.putShort((short) 0);
        DatabaseEntry entry = new DatabaseEntry(buffer.array());
        return entry;
    }
    
    public void add(long tweetId) {
        DatabaseEntry keyE = getKeyEntry(tweetId);
        DatabaseEntry valueE = getValueEntry();
        try {
                m_db.put(null, keyE, valueE);
        } catch (DatabaseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
        }
    }

    public boolean tweetIdExists(long tweetId) {
    	
    	DatabaseEntry keyE = getKeyEntry(tweetId);
    	DatabaseEntry valueE = new DatabaseEntry();

        try {
            OperationStatus opStat = m_db.get(null, keyE, valueE, LockMode.DEFAULT);

            if ( opStat == OperationStatus.NOTFOUND ) {
            	
            	return false;
            } else {
            	
            	return true;
            }
            
        } catch (DatabaseException e) {
            e.printStackTrace();
        }
        return false;
    }
	
	public void crawlFavorites(String userListFileName) {

		Vector<String> userList = new Vector<String>();

		try {
			File inFile = new File(userListFileName);
			// use buffering, reading one line at a time
			// FileReader always assumes default encoding is OK!
			BufferedReader input = new BufferedReader(new FileReader(inFile));
			try {
				String line = null; // not declared within while loop
				/*
				 * readLine is a bit quirky : it returns the content of a line
				 * MINUS the newline. it returns null only for the END of the
				 * stream. it returns an empty String if two newlines appear in
				 * a row.
				 */
				while ((line = input.readLine()) != null) {
					userList.add(line);
				}
			} finally {
				input.close();
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}

		// Got list of users, loop through and get favorites

		try {
			
			BufferedWriter outFav = new BufferedWriter(new FileWriter(new File(favFile)));
			BufferedWriter outTweet = new BufferedWriter(new FileWriter(new File(tweetFile)));
			
			Iterator<String> userIt = userList.iterator();
			while (userIt.hasNext()) {

				String user = userIt.next();
				List<Status> userFav = new ArrayList<Status>();
				List<Status> temp;

				for (int i = 0; i < 1; i++) {

					try {
						temp = twitter.getFavorites(user, i);
						System.out.println("HI");
						if (!temp.isEmpty()) {
							userFav.addAll(temp);
						} else {
							break;
						}
						
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							
						}

					} catch (TwitterException te) {
						System.out.println("Failed to get messages: "
								+ te.getMessage());
						System.exit(-1);
					}
				}

				// Have the favorited statii for this user
				Iterator<Status> statusIt = userFav.iterator();

				while (statusIt.hasNext()) {

					Status favStatus = statusIt.next();
					outFav.write(user +":"+ favStatus.getId() +"\n");
					
					// Check if we have seen this tweet yet
					if ( !tweetIdExists(favStatus.getId()) ) {

						add(favStatus.getId());
						
						// dbId\ntweetId\n\nuser\ntime\ncontents
						String tweetRec = "";
						tweetRec += "tweetId:"+ favStatus.getId() +"\n";
						tweetRec += "user:"+ favStatus.getUser().getScreenName() +"\n";
						tweetRec += "time:"+ favStatus.getCreatedAt() +"\n";
						tweetRec += "text:"+ favStatus.getText() +"\n";
						tweetRec += "**-*-*--*---**\n";
						outTweet.write(tweetRec);
					}
				}
			}
			
			outFav.close();
			outTweet.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	public static void main(String[] args) {

		TwitterCrawler tc = new TwitterCrawler("../data/test", "tweetIdDb");
		tc.favFile = "../data/testFavFile.txt";
		tc.tweetFile = "../data/testTweetFile.txt";
		
		tc.crawlFavorites("../data/testUserFile.txt");
	}
}
